#include <iostream>

// wxWidgets "Hello World" Program
// For compilers that support precompilation, includes "wx/wx.h".
//#define __WXGTK__
//#define __WXX11__
#include <wx/wxprec.h>
#ifndef WX_PRECOMP
#include <wx/wx.h>
#endif
#include <wx/dialog.h>
#include <wx/sizer.h>
#include <wx/button.h>
#include <wx/statline.h>
#include <wx/stattext.h>
#include <wx/listbox.h>
#include <map>

#include "data/PreferenceStorage.h"
#include "undefined/PreferenceScreen.h"
#include "view/PreferencesFrame.h"
#include "model/MyTagApp.h"
#include "model/PreferenceCore.h"
/*
 * view list
 * query
struct DefaultValues{
    const static char* a1 = "";
    static char* a2 = "";
};*/

static const long ID_STATICTEXT1= wxNewId();;
static const long ID_BUTTON1 = wxNewId();;
static const long ID_STATICLINE1= wxNewId();;
static const long ID_BUTTON2= wxNewId();;
static const long ID_LISTBOX1= wxNewId();;



//wxString a2 = "";
//list
class MyPre: public PreferenceScreen{
    //friend class SqlitePreferenceStorage;
    std::vector<ViewList*> list;

    void buildList() override{
        list.push_back(new ViewList( KEY_MY_KEY1, "title1", INPUT ));
        list.push_back(new ViewList( KEY_MY_KEY2, "title2", INPUT ));
    }

    ViewList* getTitle( wxString key )override{
        std::vector<ViewList* >::iterator iterator;
        for( iterator= list.begin(); iterator!=list.end();++iterator ){
            if( iterator.operator*()->key.IsSameAs( key )){
                return iterator.operator*();
            }
        }
        return nullptr;
    }

    PreferenceView* getViewItem( PreferenceItem * item ){
        ViewList* viewList = getTitle( item->getKey() );
        if( viewList ){
            return  new PreferenceView( item, viewList->type, viewList->title ) ;
        }
        return nullptr;
    }
    /*
     * key
     */
    void buildViewList(){
        PreferenceView * preferenceView;
        //
        vector<PreferenceItem*> preferences = storage->getPreferences();
        vector<PreferenceItem*>::iterator _iterator;
        //wxTextCtrl *titleCtrl, *valueCtrl, *statusCtrl;
        //wxBoxSizer *BoxSizer2 = new wxBoxSizer(wxVERTICAL);
        for(_iterator = preferences.begin();_iterator!=preferences.end(); _iterator++ ) {
            //preferenceView = new PreferenceView( _iterator.operator*(), INPUT, "" ) ;
            //this->preferenceViews.push_back( preferenceView );
            preferenceView = getViewItem( _iterator.operator*() );
            if( preferenceView ) {
                //_iterator.
                this->preferenceViews.push_back(preferenceView);
            }
        }
    }

    static SqlitePreferenceStorage *storage;
    MyPre(){
        //storage = new SqlitePreferenceStorage::(APP_TAG);
        //storage = SqlitePreferenceStorage::getDefaultSharedPreferences( MyTagApp::getInstance()->getAppTag() );

        buildList();
    }
    static MyPre* myPre;

    static wxPanel *m_panel;
    static wxListCtrl *m_listCtrl;
public:
    static MyPre* getInstance(){
        if( myPre== nullptr )
            myPre = new MyPre();
        return myPre;
    }

    //
    static void init(){
        storage->Init();
    }

    ~MyPre(){
        delete storage;
        std::vector<ViewList* >::iterator iterator;
        for( iterator= list.begin(); iterator!=list.end();++iterator ){
            delete iterator.operator*();
        }
    }

    //setup init preference data
    //
    static int setup(){
        wxString key(KEY_MY_KEY1);
        wxString defaultValue("value1");
        //wxString key(KEY_MY_KEY2);
        //wxString defaultValue("value2");
        //
        storage->add( new PreferenceItem( key, defaultValue, defaultValue, false )) ;
        storage->add( new PreferenceItem( KEY_MY_KEY2, "value2", "value2", false )) ;
        storage->Save();
        return 0;
    }

    //use sqlite
    //get default value and current value, mixed
    static wxString QueryValue( const wxString& key ){
        //update current value
        storage->Load();
        vector<PreferenceItem*> preferences = storage->getPreferences();
        vector<PreferenceItem*>::iterator _iterator;
        wxString value;
        bool found = false;
        for(_iterator = preferences.begin();_iterator!=preferences.end(); _iterator++ ) {
            if( _iterator.operator*()->getKey().IsSameAs( key ) ){
                //null?
                if( _iterator.operator*()->getValueIsNull()){
                    value = _iterator.operator*()->getDefaultValue();
                }else
                    value = _iterator.operator*()->getValue();
                break;
            }
        }
        return value;
    }

    static int PutValue( const wxString& key, const wxString& value  ){
        return storage->updateItem( key, value );
    }
public:
    static wxString get_my_key1(){
        return QueryValue( KEY_MY_KEY1 );
    }
    static wxString get_my_key2(){
        return QueryValue( KEY_MY_KEY2 );
    }

    /*
     * key, type
     * mix to build the PreferenceView( PreferenceItem )
     * ListBox1 = new wxListBox(this, ID_LISTBOX1, wxDefaultPosition, wxDefaultSize, 0, 0, 0, wxDefaultValidator, _T("ID_LISTBOX1"));
    BoxSizer1->Add(ListBox1, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
     BoxSizer1
    */
    void BuildView( wxDialog* dialog ){

    }

    //StaticText1 = new wxStaticText(this, ID_STATICTEXT1, _("Welcome to\nwxWidgets"), wxDefaultPosition, wxDefaultSize, 0, _T("ID_STATICTEXT1"));
    //    BoxSizer1->Add(StaticText1, 100, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 100);
    //wxFrame
    //    m_imageListNormal = new wxImageList(32, 32, true);
    //m_imageListNormal->Add( wxIcon("icon1", wxBITMAP_TYPE_ICO_RESOURCE) );
    //
    void BuildView( wxListBox* listBox ) {

    }

    //wxFrame
    static void BuildView( ) {
        //PreferenceFrame *frame = new PreferenceFrame("");
        storage->Load();
        vector<PreferenceItem*> preferences = storage->getPreferences();
        vector<PreferenceItem*>::iterator _iterator;

        //
        for(_iterator = preferences.begin();_iterator!=preferences.end(); _iterator++ ) {

        }
    }

    static void BuildView( wxFrame *frame ) {
        //PreferenceFrame *frame = new PreferenceFrame("");
        storage->Load();
        m_panel = new wxPanel( frame, wxID_ANY );
        /*
        m_listCtrl = new wxListCtrl(m_panel, LIST_CTRL,
                                            wxDefaultPosition, wxDefaultSize,
                                            wxLC_REPORT | wxLC_SINGLE_SEL | wxBORDER_THEME );
*/      frame->SetClientSize(wxSize(600,800));
        //wxListBox *listBox = new wxListBox( m_panel, wxID_ANY );
        auto* const baseSizer = new wxBoxSizer(wxVERTICAL);
        //CreateList();
        wxPanel *panel;
        wxBoxSizer* listItemSizer;
        //vector<PreferenceItem*> preferences = storage->getPreferences();
        vector<PreferenceView*>::iterator _iterator;
        //
        getInstance()->buildViewList();
        //getInstance()->preferenceViews;
        wxTextCtrl *titleCtrl, *valueCtrl, *statusCtrl;
        wxBoxSizer *BoxSizer2 ;//= new wxBoxSizer(wxHORIZONTAL);
        for(_iterator = getInstance()->preferenceViews.begin();
                _iterator!=getInstance()->preferenceViews.end(); _iterator++ ) {
            //InsertItemInReportView( m_listCtrl, _iterator.operator*() );
            //long tmp = m_listCtrl->InsertItem( idx, _iterator.operator*()->getKey());
            //m_listCtrl->SetItemData( tmp, total );

            //buf.Printf("Col 1, item %d", i);
            //m_listCtrl->SetItem(tmp, 1, _iterator.operator*()->getValue());

            //buf.Printf("Item %d in column 2", i);
            //m_listCtrl->SetItem(tmp, 2, _iterator.operator*()->getDefaultValue());
            //listItemSizer = new wxBoxSizer(wxHORIZONTAL);
            idx ++;
            //printf( "%d\n", idx );
            //panel = new wxPanel( listBox, wxID_ANY );
            //textCtrl = new wxTextCtrl( frame, wxID_ANY, _iterator.operator*()->getKey() );
            BoxSizer2 = new wxBoxSizer(wxHORIZONTAL);
            titleCtrl = new wxTextCtrl( frame,  wxID_ANY, _iterator.operator*()->getTitle(),
                                        wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_TEXTCTRL1"));
            //sizer->Add( panel, wxSizerFlags(idx ).Expand().Border() );
            //listItemSizer->Add(textCtrl);
            //sizer->Add( textCtrl, wxSizerFlags(1).Expand().Border());
            BoxSizer2->Add( titleCtrl, idx,
                           wxALL|wxALIGN_CENTER_HORIZONTAL, 4);
            valueCtrl = new wxTextCtrl( frame,  wxID_ANY, _iterator.operator*()->getValue(),
                                        wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_TEXTCTRL1"));
            BoxSizer2->Add( valueCtrl, idx,
                            wxALL|wxALIGN_CENTER_HORIZONTAL, 4);
            baseSizer->Add(BoxSizer2, 0,
                           wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 4);
        }
        //textCtrl = new wxTextCtrl( frame,  wxID_ANY, _("Text"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_TEXTCTRL1"));
        //BoxSizer2->Add( textCtrl, 10,
       //                 wxALL|wxALIGN_CENTER_HORIZONTAL, 4);
        //textCtrl = new wxTextCtrl( frame,  wxID_ANY, _("Text"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_TEXTCTRL1"));
        //BoxSizer2->Add( textCtrl, 10,
           //             wxALL|wxALIGN_CENTER_HORIZONTAL, 4);
        /*
        wxButton *Button1 = new wxButton( frame, ID_BUTTON1, _("About"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_BUTTON1"));
        BoxSizer2->Add(Button1, 1,
                       wxALL|wxALIGN_CENTER_HORIZONTAL, 29);
        wxStaticLine *StaticLine1 = new wxStaticLine(frame, ID_STATICLINE1, wxDefaultPosition, wxSize(10,-1), wxLI_HORIZONTAL, _T("ID_STATICLINE1"));
        BoxSizer2->Add(StaticLine1, 0,
                       wxALL|wxEXPAND, 4);
        wxButton *Button2 = new wxButton(frame, ID_BUTTON2, _("Quit"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_BUTTON2"));
        BoxSizer2->Add(Button2, 1,
                       wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 4);*/
        baseSizer->Add(BoxSizer2, 0,
                       wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 4);
        frame->SetSizer(baseSizer);
        //SetSizer(BoxSizer1);
        frame->Layout();
        //sizer->Add(m_listCtrl, wxSizerFlags(2).Expand().Border());
        //sizer->Add(m_logWindow, wxSizerFlags(1).Expand().Border());
        //sizer->Add( m_panel, wxSizerFlags(1).Expand().Border());
        //baseSizer->Add( listBox, wxSizerFlags(1).Expand().Border());
        //m_panel->SetSizer(baseSizer);

        //frame->SetClientSize(baseSizer->GetBestSize());
    }

    static void CreateList(){
        //m_listCtrl->SetImageList(m_imageListSmall, wxIMAGE_LIST_SMALL);

        // note that under MSW for SetColumnWidth() to work we need to create the
        // items with images initially even if we specify dummy image id

        wxListItem itemCol;
        itemCol.SetText("Column 1");
        itemCol.SetImage(-1);
        m_listCtrl->InsertColumn(0, itemCol);

        //
        itemCol.SetText("Column 2 (auto size excluding header)");
        itemCol.SetAlign(wxLIST_FORMAT_CENTRE);
        m_listCtrl->InsertColumn(1, itemCol);

        //
        itemCol.SetText("Column 3 (auto size including header)");
        itemCol.SetAlign(wxLIST_FORMAT_RIGHT);
        m_listCtrl->InsertColumn(2, itemCol);

        // to speed up inserting we hide the control temporarily
        m_listCtrl->Hide();

        wxStopWatch sw;

        int total = m_listCtrl->GetItemCount(); // 获取当前元素数量

        vector<PreferenceItem*> preferences = storage->getPreferences();
        vector<PreferenceItem*>::iterator _iterator;
        for(_iterator = preferences.begin();_iterator!=preferences.end(); _iterator++ ) {
            //InsertItemInReportView( m_listCtrl, _iterator.operator*() );
            long tmp = m_listCtrl->InsertItem( idx, _iterator.operator*()->getKey());
            m_listCtrl->SetItemData( tmp, total );

            //buf.Printf("Col 1, item %d", i);
            m_listCtrl->SetItem(tmp, 1, _iterator.operator*()->getValue());

            //buf.Printf("Item %d in column 2", i);
            m_listCtrl->SetItem(tmp, 2, _iterator.operator*()->getDefaultValue());
            idx ++;
        }
        //m_listCtrl->AppendColumn()
        /*
        for ( int i = 0; i < m_numListItems; i++ ){
            //
            m_listCtrl->InsertItemInReportView(i);
        }*/
        m_listCtrl->Show();

        // we leave all mask fields to 0 and only change the colour
        /*
        wxListItem item;
        item.m_itemId = 0;
        item.SetTextColour(*wxRED);
        m_listCtrl->SetItem( item );

        item.m_itemId = 2;
        item.SetTextColour(*wxGREEN);
        m_listCtrl->SetItem( item );

        item.m_itemId = 4;
        item.SetTextColour(*wxLIGHT_GREY);
        item.SetFont(*wxITALIC_FONT);
        item.SetBackgroundColour(*wxRED);
        m_listCtrl->SetItem( item );

        m_listCtrl->SetTextColour(*wxBLUE);

        // Set images in columns
        m_listCtrl->SetItemColumnImage(1, 1, 0);

        wxListItem info;
        info.SetImage(0);
        info.SetId(3);
        info.SetColumn(2);
        m_listCtrl->SetItem(info);

        // test SetItemFont too
        m_listCtrl->SetItemFont(0, *wxITALIC_FONT);
        */
        m_listCtrl->SetColumnWidth( 0, wxLIST_AUTOSIZE );
        m_listCtrl->SetColumnWidth( 1, wxLIST_AUTOSIZE );
        m_listCtrl->SetColumnWidth( 2, wxLIST_AUTOSIZE_USEHEADER );
    }

    static int idx;// = 0;
    static void InsertItemInReportView( wxListCtrl *m_listCtrl, PreferenceItem* item)
    {
        //wxString buf;;
        //buf.Printf("This is item %d", 0);

    }
};

SqlitePreferenceStorage * MyPre::storage = nullptr;
MyPre* MyPre::myPre = nullptr;
wxPanel *MyPre::m_panel;
wxListCtrl *MyPre::m_listCtrl;
int MyPre::idx = 0;

//SqlitePreferenceStorage *MyPreHelper::storage = nullptr;
//MyPreHelper* MyPreHelper::myPreHelper = nullptr;


wxIMPLEMENT_APP(MyTagApp);



